package drds.plus.repository.mysql.spi;

import drds.plus.datanode.api.Connection;
import drds.plus.datanode.api.DatasourceManager;
import drds.plus.datanode.api.PreparedStatement;
import drds.plus.executor.ExecuteContext;
import drds.plus.executor.ExecutorException;
import drds.plus.executor.cursor.cursor.ISortingCursor;
import drds.plus.executor.cursor.cursor.impl.SortingCursor;
import drds.plus.executor.cursor.cursor_metadata.CursorMetaData;
import drds.plus.executor.record_codec.record.Record;
import drds.plus.executor.repository.IDatasourceManagerGetter;
import drds.plus.executor.table.ITable;
import drds.plus.executor.utils.Utils;
import drds.plus.repository.mysql.utils.MysqlRepoUtils;
import drds.plus.sql_process.abstract_syntax_tree.configuration.IndexMapping;
import drds.plus.sql_process.abstract_syntax_tree.configuration.TableMetaData;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.query.QueryWithIndex;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;

@Slf4j
public class Table implements ITable {

    @Setter
    @Getter
    protected String dataNodeId;
    @Setter
    @Getter
    protected IDatasourceManagerGetter dataNodeDataSourceGetter = new DatasourceManagerGetterImpl();
    @Setter
    @Getter
    protected DatasourceManager datasourceManager;
    @Setter
    @Getter
    protected TableMetaData tableMetaData;
    // 判断是否已经做过了查询
    @Setter
    @Getter
    protected boolean isSelect = false;

    public Table(String dataNodeId, DatasourceManager datasourceManager, TableMetaData tableMetaData) {
        this.dataNodeId = dataNodeId;
        this.datasourceManager = datasourceManager;
        this.tableMetaData = tableMetaData;
    }

    public void close() {

    }


    public void put(ExecuteContext executeContext, String databaseName, IndexMapping indexMapping, Record keyRecord, Record valueRecord) throws RuntimeException {
        StringBuilder columnNames = new StringBuilder("replace into ");
        columnNames.append(tableMetaData.getTableName()).append(" (");
        //
        StringBuilder columnValues = new StringBuilder(" values (");
        List valueList = new ArrayList();
        for (Entry<String, Object> entry : valueRecord.getColumnNameToValueMap().entrySet()) {
            if (entry.getValue() != null) {
                columnNames.append(entry.getKey()).append(",");
                //
                columnValues.append("?").append(",");
                valueList.add(entry.getValue());
            }
        }
        for (Entry<String, Object> entry : keyRecord.getColumnNameToValueMap().entrySet()) {
            if (entry.getValue() != null) {
                columnNames.append(entry.getKey()).append(",");
                //
                columnValues.append("?").append(",");
                valueList.add(entry.getValue());
            }
        }
        columnNames.delete(columnNames.length() - 1, columnNames.length());
        columnValues.delete(columnValues.length() - 1, columnValues.length());
        StringBuilder sql = columnNames.append(") ").append(columnValues).append(")");
        //
        Connection connection = null;
        PreparedStatement dataNodePreparedStatement = null;
        try {
            connection = datasourceManager.getConnection();
            dataNodePreparedStatement = connection.prepareDataNodePreparedStatement(sql.toString());
            int i = 1;
            for (Object object : valueList) {
                dataNodePreparedStatement.setObject(i++, object);
            }
            int rowCount = dataNodePreparedStatement.executeUpdate();
            if (rowCount <= 0) {
                throw new ExecutorException("execute failed : " + keyRecord.getColumnNameList());
            }
        } catch (SQLException e) {
            log.error("error: 底层数据库异常", e);
            throw new RuntimeException(e);
        } finally {
            try {
                if (dataNodePreparedStatement != null) {
                    dataNodePreparedStatement.close();
                }
            } catch (SQLException e) {
                log.warn("数据库关闭异常", e);
            }

            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                log.warn("数据库关闭异常", e);
            }
        }
    }


    public void delete(ExecuteContext executeContext, String databaseName, IndexMapping indexMapping, Record key) throws RuntimeException {
        StringBuilder sql = new StringBuilder("delete from ");
        sql.append(tableMetaData.getTableName()).append(" where ");
        if (key != null) {
            String and = " and ";
            int size = key.getColumnNameToValueMap().size();
            int i = 0;
            for (Entry<String, Object> entry : key.getColumnNameToValueMap().entrySet()) {
                sql.append(entry.getKey()).append("='").append(entry.getValue()).append("'");
                if (++i < size) {
                    sql.append(and);
                }
            }
        } else {
            log.warn("注意！删除了该表所有信息：" + tableMetaData.getTableName());
        }

        Connection connection = null;
        PreparedStatement dataNodePreparedStatement = null;
        try {
            connection = datasourceManager.getConnection();
            dataNodePreparedStatement = connection.prepareDataNodePreparedStatement(sql.toString());
            int rowCount = dataNodePreparedStatement.executeUpdate();
            if (rowCount < 0) {
                throw new ExecutorException("execute failed : " + key.getColumnNameList() + "\n\r ");
            }
        } catch (SQLException e) {
            log.error("error: 底层数据库异常", e);
        } finally {
            try {
                if (dataNodePreparedStatement != null) {
                    dataNodePreparedStatement.close();
                }
            } catch (SQLException e) {
                log.warn("数据库关闭异常", e);
            }

            try {
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                log.warn("数据库关闭异常", e);
            }
        }
    }

    public Record get(ExecuteContext executeContext, String databaseName, IndexMapping indexMapping, Record key) {
        //throw new RuntimeException("暂时抛异常");
        //默认返回为null
        return null;
    }

    public long count() {
        return 0;
    }

    public ISortingCursor getCursor(ExecuteContext executeContext, String indexMetaName, IndexMapping indexMapping) throws RuntimeException {
        throw new UnsupportedOperationException();
    }

    public ISortingCursor getCursor(ExecuteContext executeContext, QueryWithIndex queryWithIndex, IndexMapping indexMapping) throws RuntimeException {
        JdbcHandler jdbcHandler = ((RepositoryImpl) executeContext.getRepository()).getJdbcHandler(executeContext, queryWithIndex, this.dataNodeDataSourceGetter);
        CursorMetaData cursorMetaData = Utils.convertIndexMetaDataToCursorMetaData(indexMapping);
        CursorImpl cursor = new CursorImpl(queryWithIndex, queryWithIndex.isStreaming(), cursorMetaData, jdbcHandler);
        return new SortingCursor(cursor, cursorMetaData, MysqlRepoUtils.buildOrderBy(queryWithIndex, indexMapping));
    }
}
